/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Engine2D.math;


/**
 *
 * @author Garys
 */
public class Matrix2d {

    /**
     * 
     */
    protected double[][] matrix = new double[2][2];

    /**
     * 
     * @param matrix
     */
    public Matrix2d(double[] matrix) {

        this.matrix[0][0] = matrix[0];
        this.matrix[0][1] = matrix[1];
        this.matrix[1][0] = matrix[2];
        this.matrix[1][1] = matrix[3];

    }

    /**
     * 
     * @param x
     * @param y
     */
    public Matrix2d(Vector2d x, Vector2d y) {
        this.matrix[0][0] = x.x;
        this.matrix[0][1] = x.y;
        this.matrix[1][0] = y.x;
        this.matrix[1][1] = y.y;
    }

    /**
     * 
     * @param x
     * @param y
     */
    public Matrix2d(double[] x, double[] y) {
        this.matrix[0][0] = x[0];
        this.matrix[0][1] = x[1];
        this.matrix[1][0] = y[0];
        this.matrix[1][1] = y[1];
    }

    /**
     * 
     * @param xx
     * @param xy
     * @param yx
     * @param yy
     */
    public Matrix2d(double xx, double xy, double yx, double yy) {
        this.matrix[0][0] = xx;
        this.matrix[0][1] = xy;
        this.matrix[1][0] = yx;
        this.matrix[1][1] = yy;
    }

    /**
     * 
     * @return
     */
    public Matrix2d negateMatrix2d() {
        return new Matrix2d(-matrix[0][0], -matrix[0][1], -matrix[1][0], -matrix[1][1]);
    }

    /**
     * 
     * @param matrix2d
     * @return
     */
    public Matrix2d addMatrix2d(Matrix2d matrix2d) {

        return new Matrix2d(this.matrix[0][0] + matrix2d.matrix[0][0], this.matrix[0][1] + matrix2d.matrix[0][1],
                this.matrix[1][0] + matrix2d.matrix[1][0], this.matrix[1][1] + matrix2d.matrix[1][1]);

    }

    /**
     * 
     * @param matrix2d
     */
    public void addMatrix2dToThis(Matrix2d matrix2d) {
        this.matrix[0][0] += matrix2d.matrix[0][0];
        this.matrix[0][1] += matrix2d.matrix[0][1];
        this.matrix[1][0] += matrix2d.matrix[1][0];
        this.matrix[1][1] += matrix2d.matrix[1][1];
    }

    /**
     * 
     * @param matrix2d
     * @return
     */
    public Matrix2d subtractMatrix2d(Matrix2d matrix2d) {

        return new Matrix2d(this.matrix[0][0] - matrix2d.matrix[0][0], this.matrix[0][1] - matrix2d.matrix[0][1],
                this.matrix[1][0] - matrix2d.matrix[1][0], this.matrix[1][1] - matrix2d.matrix[1][1]);

    }

    /**
     * 
     * @param matrix2d
     */
    public void subtractMatrix2dToThis(Matrix2d matrix2d) {
        this.matrix[0][0] -= matrix2d.matrix[0][0];
        this.matrix[0][1] -= matrix2d.matrix[0][1];
        this.matrix[1][0] -= matrix2d.matrix[1][0];
        this.matrix[1][1] -= matrix2d.matrix[1][1];
    }

    /**
     * 
     * @param scale
     * @return
     */
    public Matrix2d scaleMatrix2d(double scale) {

        return new Matrix2d(this.matrix[0][0] * scale, this.matrix[0][1] * scale,
                this.matrix[1][0] * scale, this.matrix[1][1] * scale);

    }

    /**
     * 
     * @param scale
     */
    public void scaleMatrix2dToThis(double scale) {
        this.matrix[0][0] *= scale;
        this.matrix[0][1] *= scale;
        this.matrix[1][0] *= scale;
        this.matrix[1][1] *= scale;
    }

    /**
     * 
     * @param matrix2d
     * @return
     */
    public Matrix2d multiplyMatrix2d(Matrix2d matrix2d) {

        return new Matrix2d(this.matrix[0][0] * matrix2d.matrix[0][0], this.matrix[0][1] * matrix2d.matrix[0][1],
                this.matrix[1][0] * matrix2d.matrix[1][0], this.matrix[1][1] * matrix2d.matrix[1][1]);

    }

    /**
     * 
     * @param matrix2d
     */
    public void multiplyMatrix2dToThis(Matrix2d matrix2d) {

        this.matrix[0][0] *= matrix2d.matrix[0][0];
        this.matrix[0][1] *= matrix2d.matrix[0][1];
        this.matrix[1][0] *= matrix2d.matrix[1][0];
        this.matrix[1][1] *= matrix2d.matrix[1][1];

    }

    /**
     * 
     * @param row
     * @param vector2d
     */
    public void setRow(int row, Vector2d vector2d) {
        matrix[row][0] = vector2d.x;
        matrix[row][1] = vector2d.y;
    }

    /**
     * 
     * @param column
     * @param vector2d
     */
    public void setColumn(int column, Vector2d vector2d) {
        matrix[0][column] = vector2d.x;
        matrix[1][column] = vector2d.y;
    }

    /**
     * 
     * @param row
     * @return
     */
    public Vector2d getRow(int row) {
        return new Vector2d(matrix[row][0], matrix[row][1]);
    }

    /**
     * 
     * @param column
     * @return
     */
    public Vector2d getColumn(int column) {
        return new Vector2d(matrix[0][column], matrix[1][column]);
    }

    /**
     * 
     */
    public void setIdentity() {
        matrix[0][0] = 1.0d;
        matrix[0][1] = 0d;
        matrix[1][0] = 0d;
        matrix[1][1] = 1.0d;
    }

    /**
     * 
     */
    public void setZero() {
        matrix[0][0] = 0d;
        matrix[0][1] = 0d;
        matrix[1][0] = 0d;
        matrix[1][1] = 0d;
    }

    /**
     * 
     */
    public void transpose() {
        double i = matrix[0][1];
        matrix[0][1] = matrix[1][0];
        matrix[1][0] = i;
    }

    /**
     * 
     * @param matrix2d
     */
    public void getTranspose(Matrix2d matrix2d) {

        matrix2d.matrix[0][0] = matrix[0][0];
        matrix2d.matrix[0][1] = matrix[1][0];
        matrix2d.matrix[1][0] = matrix[0][1];
        matrix2d.matrix[1][1] = matrix[1][1];

    }

    /**
     * 
     * @return
     */
    public double determinate() {
        return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
    }

    /**
     * 
     * @param vector2d
     */
    public void scale(Vector2d vector2d) {
        matrix[0][0] = vector2d.x;
        matrix[0][1] = 0.0d;
        matrix[1][0] = 0.0d;
        matrix[1][1] = vector2d.y;
    }

    /**
     * 
     * @param x
     * @param y
     */
    public void scale(double x, double y) {
        matrix[0][0] = x;
        matrix[0][1] = 0.0d;
        matrix[1][0] = 0.0d;
        matrix[1][1] = y;
    }

    /**
     * 
     * @param angle
     */
    public void rotate(double angle) {
        
        double cosAngle = Math.cos(angle);
        double sinAngle = Math.sin(angle);
        matrix[0][0] = cosAngle;
        matrix[0][1] = sinAngle;
        matrix[1][0] = -sinAngle;
        matrix[1][1] = cosAngle;
        
    }

    @Override
    public String toString() {
        return "Matrix2d{" + "matrix=" + 
                matrix[0][0] +" "+
                matrix[0][1] +" "+
                matrix[1][0] +" "+
                matrix[1][1];
    }
    
    /**
     * 
     * @param args
     */
    public static void main(String[] args) {
        Matrix2d matrix2d = new Matrix2d(1d, 0d, 0d, 1d);
        
        for (double i = 0; i < 10; i++) {
            matrix2d.rotate(1d+i);
            System.out.println(matrix2d.toString());
            
        }
    }
    
   
}
